#!/usr/bin/php

<?php

use Symfony\Component\Yaml\Yaml;

define('ROOT', dirname(__DIR__));

require ROOT . '/vendor/autoload.php';

const types = [
    'blob'     => '',
    'bool'     => 'bool',
    'char'     => 'string',
    'datetime' => '\DateTimeInterface',
    'html'     => 'string',
    'int'      => 'int',
    'numeric'  => 'float',
    'serial'   => 'int',
    'text'     => 'string',
    'varchar'  => 'string',
];

$path = Yaml::parseFile(ROOT . '/config/services.yaml')['services']['app.util.schemadef_driver']['arguments'][0];
$path = str_replace('%kernel.project_dir%', ROOT, $path);

$files = glob($path . '/*.php');

foreach ($files as $file) {
    require_once $file;

    $declared = get_declared_classes();
    $class    = end($declared);

    $no_ns_class  = preg_replace('/.*?\\\\/', '', $class);
    $schema       = $class::schemaDef();
    $fields       = array_keys($schema['fields']);
    $fields_code  = [];
    $methods_code = [];
    foreach ($fields as $field) {
        $nullable       = !@$schema['fields'][$field]['not null'] ? '?' : '';
        $type           = types[$schema['fields'][$field]['type']];
        $type           = $type !== '' ? $nullable . $type : $type;
        $method_name    = str_replace(' ', '', ucwords(str_replace('_', ' ', $field)));
        $fields_code[]  = "    private {$type} \${$field};";
        $methods_code[] = "    public function set{$method_name}({$type} \${$field}): self " .
                        "{ \$this->{$field} = \${$field}; return \$this; }" . "\n" .
                        "    public function get{$method_name}()" . ($type !== '' ? ': ' . $type : '') .
                        "{ return \$this->{$field}; }" . "\n";
    }

    $fields_code  = implode("\n", $fields_code);
    $methods_code = implode("\n", $methods_code) . "\n";

    $begin = '// {{{ Autocode';
    $end   = '// }}} Autocode';
    $code  = "
    {$begin}

{$fields_code}

{$methods_code}

    {$end}
";

    foreach (['/\\//' => '\\/', '/ /' => '\\ '] as $from => $to) {
        $begin = preg_replace($from, $to, $begin);
        $end   = preg_replace($from, $to, $end);
    }

    $in_file  = file_get_contents($file);
    $out_file = preg_replace("/\\s*{$begin}[^\\/]*{$end}/m", $code, $in_file);

    file_put_contents($file, $out_file);
}
